import 'sort.dart';

/// 分页请求接口
abstract class BasePageRequest {
  /// 页码（从1开始）
  int get pageNumber;

  /// 页大小
  int get pageSize;

  /// 排序
  Sort get sort;

  /// 偏移量
  int get offset => (pageNumber - 1) * pageSize;

  /// 是否有上一页
  bool get hasPrevious => pageNumber > 1;

  /// 获取上一页
  BasePageRequest? get previous;

  /// 获取下一页
  BasePageRequest get next;

  /// 获取第一页
  BasePageRequest get first;

  /// 是否分页
  bool get isPaged => pageSize > 0;

  /// 是否有排序
  bool get isSorted => sort.isNotEmpty;
}

/// 分页请求实现
class PageRequest implements BasePageRequest {
  @override
  final int pageNumber;

  @override
  final int pageSize;

  @override
  final Sort sort;

  const PageRequest(
    this.pageNumber,
    this.pageSize, [
    this.sort = const Sort.unsorted(),
  ]);

  /// 创建默认分页请求
  factory PageRequest.of(int pageNumber, int pageSize) {
    return PageRequest(pageNumber, pageSize);
  }

  /// 创建带排序的分页请求
  factory PageRequest.withSort(int pageNumber, int pageSize, Sort sort) {
    return PageRequest(pageNumber, pageSize, sort);
  }

  /// 创建第一页请求
  factory PageRequest.first(int pageSize, [Sort sort = const Sort.unsorted()]) {
    return PageRequest(1, pageSize, sort);
  }

  @override
  int get offset => (pageNumber - 1) * pageSize;

  @override
  bool get hasPrevious => pageNumber > 1;

  @override
  BasePageRequest? get previous {
    return hasPrevious ? PageRequest(pageNumber - 1, pageSize, sort) : null;
  }

  @override
  BasePageRequest get next {
    return PageRequest(pageNumber + 1, pageSize, sort);
  }

  @override
  BasePageRequest get first {
    return PageRequest(1, pageSize, sort);
  }

  @override
  bool get isPaged => pageSize > 0;

  @override
  bool get isSorted => sort.isNotEmpty;

  /// 获取指定页码的分页请求
  PageRequest withPage(int pageNumber) {
    return PageRequest(pageNumber, pageSize, sort);
  }

  /// 获取指定页大小的分页请求
  PageRequest withPageSize(int pageSize) {
    return PageRequest(pageNumber, pageSize, sort);
  }

  /// 获取指定排序的分页请求
  PageRequest withSort(Sort sort) {
    return PageRequest(pageNumber, pageSize, sort);
  }

  @override
  String toString() {
    return 'PageRequest{pageNumber: $pageNumber, pageSize: $pageSize, sort: $sort}';
  }

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is PageRequest &&
          runtimeType == other.runtimeType &&
          pageNumber == other.pageNumber &&
          pageSize == other.pageSize &&
          sort == other.sort;

  @override
  int get hashCode => pageNumber.hashCode ^ pageSize.hashCode ^ sort.hashCode;
}
